package top.eggcode.component.session.manager;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import top.eggcode.component.session.Session;
import top.eggcode.component.session.SimpleSession;
import top.eggcode.component.session.exception.ExpiredSessionException;
import top.eggcode.component.session.exception.InvalidSessionException;
import top.eggcode.component.session.exception.SessionException;
import top.eggcode.component.session.task.ValidationScheduler;

import java.util.Collection;

/**
 * Title: 带过期验证的会话管理器
 * Description: 提供了校验过期方法，针对所有 session
 * Date: 2021/7/31 0:14
 *
 * @author JiaQi Ding
 * @version 1.0
 */
public abstract class VerificationSessionManager extends NativeSessionManager {
    public static final long DEFAULT_VALIDATION_INTERVAL = 60 * 60 * 1000;
    private static final Logger log = LoggerFactory.getLogger(VerificationSessionManager.class);
    protected boolean schedulerEnabled;

    protected ValidationScheduler sessionValidationScheduler;

    protected long validationInterval;

    public VerificationSessionManager() {
        this.schedulerEnabled = true;
        this.validationInterval = DEFAULT_VALIDATION_INTERVAL;
    }

    public boolean isSchedulerEnabled() {
        return schedulerEnabled;
    }

    public void setSchedulerEnabled(boolean schedulerEnabled) {
        this.schedulerEnabled = schedulerEnabled;
    }

    public ValidationScheduler getSessionValidationScheduler() {
        return sessionValidationScheduler;
    }

    public void setSessionValidationScheduler(ValidationScheduler sessionValidationScheduler) {
        this.sessionValidationScheduler = sessionValidationScheduler;
    }

    private void enableSessionValidationIfNecessary() {
        ValidationScheduler scheduler = getSessionValidationScheduler();
        if (isSchedulerEnabled() && (scheduler == null || !scheduler.isEnabled())) {
            enableSessionValidation();
        }
    }

    protected ValidationScheduler createSessionValidationScheduler() {
        ValidationScheduler scheduler;
        scheduler = new ValidationScheduler(this);

        return scheduler;
    }

    protected synchronized void enableSessionValidation() {
        ValidationScheduler scheduler = getSessionValidationScheduler();
        if (scheduler == null) {
            scheduler = createSessionValidationScheduler();
            setSessionValidationScheduler(scheduler);
        }
        // it is possible that that a scheduler was already created and set via 'setSessionValidationScheduler()'
        // but would not have been enabled/started yet
        if (!scheduler.isEnabled()) {
            if (log.isInfoEnabled()) {
                log.info("Enabling session validation scheduler...");
            }
            scheduler.enableSessionValidation();
            afterSessionValidationEnabled();
        }
    }

    protected void afterSessionValidationEnabled() {
    }

    @Override
    public Session start() {

        return createSession();
    }

    @Override
    protected Session createSession() {
        // 开启校验任务
        enableSessionValidationIfNecessary();

        return doCreateSession();
    }

    protected abstract Session doCreateSession() throws SessionException;

    /**
     * 校验系统会话
     */
    public void validateSessions() {
        if (log.isInfoEnabled()) {
            log.info("Validating all active sessions...");
        }

        int invalidCount = 0;

        Collection<Session> activeSessions = getActiveSessions();

        if (activeSessions != null && !activeSessions.isEmpty()) {
            for (Session s : activeSessions) {
                try {
                    validate(s);
                } catch (InvalidSessionException e) {
                    if (log.isDebugEnabled()) {
                        boolean expired = (e instanceof ExpiredSessionException);
                        String msg = "Invalidated session with id [" + s.getId() + "]" +
                                (expired ? " (expired)" : " (stopped)");
                        log.debug(msg);
                    }
                    invalidCount++;
                }
            }
        }

        if (log.isInfoEnabled()) {
            String msg = "Finished session validation.";
            if (invalidCount > 0) {
                msg += "  [" + invalidCount + "] sessions were stopped.";
            } else {
                msg += "  No sessions were stopped.";
            }
            log.info(msg);
        }
    }

    protected void validate(Session session) throws InvalidSessionException {

        try {
            doValidate(session);
        } catch (ExpiredSessionException ese) {
            onExpiration(session);
            throw ese;
        } catch (InvalidSessionException ise) {
            afterExpired(session);
            throw ise;
        }
    }

    protected void doValidate(Session session) throws InvalidSessionException {
        if (session instanceof SimpleSession) {
            ((SimpleSession) session).validate();
        } else {
            throw new IllegalStateException("session类型错误");
        }
    }


    /**
     * 过期后的处理
     *
     * @param session
     */
    protected void afterExpired(Session session) {

/*        if (isDeleteInvalidSessions()) {
            delete(session);
        }*/


    }

    /**
     * 当过期时
     *
     * @param session
     */
    protected void onExpiration(Session session) {

    }

    protected abstract Collection<Session> getActiveSessions();


}
